package com.supreme.cacheserver.controller;

import com.supreme.commonboot.utils.AjaxResp;
import org.springframework.data.geo.Distance;
import org.springframework.data.geo.GeoResults;
import org.springframework.data.geo.Metrics;
import org.springframework.data.geo.Point;
import org.springframework.data.redis.connection.RedisGeoCommands;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.io.Serializable;
import java.util.List;

@RestController
@RequestMapping(value = "redis-geo")
public class RedisGeoController {

    @Resource
    private RedisTemplate<String, Serializable> redisTemplate;

    @Resource
    private List<RedisTemplate<String, Serializable>> redisTemplateList;

    @GetMapping(value = "add/{key}/{value}/{position}")
    public AjaxResp add(@PathVariable(value = "key") String key,
                        @PathVariable(value = "value") String value,
                        @PathVariable(value = "position") double... position) {
        if (position.length < 2) {
            throw new IllegalArgumentException("Invalid position");
        }

        Long add = redisTemplate.opsForGeo().add(key, new Point(position[0], position[1]), value);
        return new AjaxResp(add);
    }

    @GetMapping(value = "position/{key}/{value}")
    public AjaxResp position(@PathVariable(value = "key") String key, @PathVariable(value = "value") String... value) {
        List<Point> position = redisTemplate.opsForGeo().position(key, value);
        return new AjaxResp(position);
    }

    @GetMapping(value = "distance/{key}/{value}")
    public AjaxResp distance(@PathVariable(value = "key") String key, @PathVariable(value = "value") String... value) {
        Distance distance = redisTemplate.opsForGeo().distance(key, value[0], value[1], RedisGeoCommands.DistanceUnit.KILOMETERS);
        return new AjaxResp(distance);
    }

    @GetMapping(value = "radius/{key}/{value}")
    public AjaxResp radius(@PathVariable(value = "key") String key, @PathVariable(value = "value") String value) {
        Distance distance = new Distance(200, Metrics.KILOMETERS);
        RedisGeoCommands.GeoRadiusCommandArgs args = RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs()
                .includeDistance()
                .includeCoordinates()
                .sortAscending()
                .limit(5);
        GeoResults<RedisGeoCommands.GeoLocation<Serializable>> radius = redisTemplate.opsForGeo().radius(key, value, distance, args);
        return new AjaxResp(radius);
    }

    @GetMapping(value = "hash/{key}/{value}")
    public AjaxResp hash(@PathVariable(value = "key") String key, @PathVariable(value = "value") String... value) {
        List<String> hash = redisTemplate.opsForGeo().hash(key, value);
        return new AjaxResp(hash);
    }

    @GetMapping(value = "remove/{key}/{value}")
    public AjaxResp remove(@PathVariable(value = "key") String key, @PathVariable(value = "value") String... value) {
        Long remove = redisTemplate.opsForGeo().remove(key, value);
        return new AjaxResp(remove);
    }
}
